package com.atguigu.gulimall.product.service.impl;
import com.atguigu.common.constant.ProductConstant;
import com.atguigu.gulimall.product.dao.AttrAttrgroupRelationDao;
import com.atguigu.gulimall.product.dao.AttrGroupDao;
import com.atguigu.gulimall.product.dao.CategoryDao;
import com.atguigu.gulimall.product.entity.AttrAttrgroupRelationEntity;
import com.atguigu.gulimall.product.entity.AttrGroupEntity;
import com.atguigu.gulimall.product.entity.CategoryEntity;
import com.atguigu.gulimall.product.service.AttrAttrgroupRelationService;
import com.atguigu.gulimall.product.service.AttrGroupService;
import com.atguigu.gulimall.product.vo.AttrResponseVo;
import com.atguigu.gulimall.product.vo.AttrVo;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.atguigu.common.utils.PageUtils;
import com.atguigu.common.utils.Query;
import com.atguigu.gulimall.product.dao.AttrDao;
import com.atguigu.gulimall.product.entity.AttrEntity;
import com.atguigu.gulimall.product.service.AttrService;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;


@Service
public class AttrServiceImpl extends ServiceImpl<AttrDao, AttrEntity> implements AttrService {

    @Resource
    private AttrAttrgroupRelationDao attrAttrgroupRelationDao;

    @Resource
    private CategoryDao categoryDao;

    @Resource
    private AttrAttrgroupRelationService attrAttrgroupRelationService;

    @Resource
    private AttrGroupDao attrGroupDao;

    @Autowired
    private AttrGroupService attrGroupService;

    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        IPage<AttrEntity> page = this.page(
                new Query<AttrEntity>().getPage(params),
                new QueryWrapper<AttrEntity>()
        );

        return new PageUtils(page);
    }

    @Override
    @Transactional
    public void saveAttr(AttrVo attr) {
        AttrEntity attrEntity = new AttrEntity();
//        attrEntity.setAttrName(attr.getAttrName());    这样很麻烦，我们使用spring提供的工具类BeanUtils
        BeanUtils.copyProperties(attr,attrEntity);   //前提条件是VO里面的属性名和PO里面的属性名是一一对应的
        //保存属性表中的数据
//        this.save(attrEntity);
        baseMapper.insert(attrEntity);
        //保存属性分组关系表的数据
        if(attr.getAttrType() == ProductConstant.AttrEnum.ATTR_TYPE_BASE.getCode()){
            AttrAttrgroupRelationEntity attrAttrgroupRelationEntity = new AttrAttrgroupRelationEntity();
            attrAttrgroupRelationEntity.setAttrId(attrEntity.getAttrId());
            Long attrGroupId = attr.getAttrGroupId();
            if(!StringUtils.isEmpty(attrGroupId)){
                attrAttrgroupRelationEntity.setAttrGroupId(attrGroupId);
                attrAttrgroupRelationDao.insert(attrAttrgroupRelationEntity);
            }

        }

    }

    @Override
    public PageUtils queryBaseAttr(Map<String, Object> params, Long catelogId, String type) {
        QueryWrapper<AttrEntity> wrapper = new QueryWrapper<>();
        wrapper.eq("attr_type","base".equalsIgnoreCase(type)?ProductConstant.AttrEnum.ATTR_TYPE_BASE.getCode():ProductConstant.AttrEnum.ATTR_TYPE_SALE.getCode());
        if(catelogId != 0){
            wrapper.eq("catelog_id",catelogId);
        }
        String key = (String) params.get("key");
        if(!StringUtils.isEmpty(key)){
            //attr_id    attr_name
            wrapper.and((item) ->{
                item.eq("attr_id",key).or().like("attr_name",key);
            });
        }
        IPage<AttrEntity> page = this.page(
                new Query<AttrEntity>().getPage(params),
                wrapper
        );
        PageUtils pageUtils = new PageUtils(page);
        List<AttrEntity> records = page.getRecords();
        List<AttrResponseVo> collect = records.stream().map((attrEntity) -> {
            AttrResponseVo attrResponseVo = new AttrResponseVo();
            BeanUtils.copyProperties(attrEntity, attrResponseVo);
            //1.设置分类和分组的名字
            CategoryEntity categoryEntity = categoryDao.selectById(attrEntity.getCatelogId());
            if(categoryEntity != null){
                attrResponseVo.setCatelogName(categoryEntity.getName());
            }
            AttrAttrgroupRelationEntity middle = attrAttrgroupRelationService.getBaseMapper().
                    selectOne(new QueryWrapper<AttrAttrgroupRelationEntity>().
                            eq("attr_id", attrResponseVo.getAttrId()));
            if("base".equalsIgnoreCase(type)){
                if (middle != null) {
                    AttrGroupEntity end = attrGroupService.getBaseMapper().selectOne(new QueryWrapper<AttrGroupEntity>()
                            .eq("attr_group_id", middle.getAttrGroupId()));

                    if(end != null){
                        attrResponseVo.setGroupName(end.getAttrGroupName());
                    }
                }
            }

            return attrResponseVo;
        }).collect(Collectors.toList());
        pageUtils.setList(collect);
        return pageUtils;
    }

    @Override
    @Cacheable(value = {"attr"},key = "'attrinfo:'+#root.args[0]")
    public AttrResponseVo getAttrInfo(Long attrId) {
        AttrEntity byId = this.getById(attrId);
        AttrResponseVo attrResponseVo = new AttrResponseVo();
        BeanUtils.copyProperties(byId,attrResponseVo);

        //设置分组信息
        if(byId.getAttrType() == ProductConstant.AttrEnum.ATTR_TYPE_BASE.getCode()){
            AttrAttrgroupRelationEntity middle = attrAttrgroupRelationDao.selectOne(
                    new QueryWrapper<AttrAttrgroupRelationEntity>().eq("attr_id", byId.getAttrId()));
            if(middle != null){
                attrResponseVo.setAttrGroupId(middle.getAttrGroupId());
                AttrGroupEntity attrGroupEntity = attrGroupDao.selectById(middle.getAttrGroupId());
                if(attrGroupEntity != null){
                    attrResponseVo.setGroupName(attrGroupEntity.getAttrGroupName());
                }
            }
        }

        ArrayList<Long> list = new ArrayList<>();
        List<Long> result = this.getCatelogPath(byId.getCatelogId(),list);
        Collections.reverse(result);
        attrResponseVo.setCatelogPath(result.toArray(new Long[result.size()]));
        CategoryEntity categoryEntity = categoryDao.selectById(byId.getCatelogId());
        if(categoryEntity != null){
            attrResponseVo.setCatelogName(categoryEntity.getName());
        }
        return attrResponseVo;
    }

    @Override
    @Transactional
    public void updateAttr(AttrVo attr) {
        AttrEntity attrEntity = new AttrEntity();
        BeanUtils.copyProperties(attr,attrEntity);
        baseMapper.update(attrEntity,new QueryWrapper<AttrEntity>().eq("attr_id",attrEntity.getAttrId()));
        //修改分组关联，即分组属性关联表
        if(attrEntity.getAttrType() == ProductConstant.AttrEnum.ATTR_TYPE_BASE.getCode()){
            AttrAttrgroupRelationEntity attrAttrgroupRelationEntity = new AttrAttrgroupRelationEntity();
            attrAttrgroupRelationEntity.setAttrGroupId(attr.getAttrGroupId());
            attrAttrgroupRelationEntity.setAttrId(attr.getAttrId());
            if(attrAttrgroupRelationDao.selectCount(new
                    QueryWrapper<AttrAttrgroupRelationEntity>().eq("attr_id",attr.getAttrId())) > 0){
                attrAttrgroupRelationDao.update(attrAttrgroupRelationEntity,new
                        QueryWrapper<AttrAttrgroupRelationEntity>().eq("attr_id",attr.getAttrId()));
            }else{
                attrAttrgroupRelationDao.insert(attrAttrgroupRelationEntity);
            }
        }

        //如果管理员本来就没给这个值进行设置，那直接是无法进行修改的，所以下面需要判断


    }

    //根据分组id，找到相关联的所有属性
    @Override
    public List<AttrEntity> getRelationAttr(Long attrgroupId) {
        List<AttrAttrgroupRelationEntity> middle = attrAttrgroupRelationDao.selectList(new QueryWrapper<AttrAttrgroupRelationEntity>().eq("attr_group_id", attrgroupId));
        List<Long>attrIds = new ArrayList<>();
        middle.forEach((item) -> attrIds.add(item.getAttrId()));
        List<AttrEntity> list = baseMapper.selectBatchIds(attrIds);
        return list;
    }

    //获取当前分组没有关联的所有属性
    @Override
    public PageUtils getNoRelationAttr(Map<String, Object> params, Long attrgroupId) {
        //1.当前分组只能关联自己所属的分类里面的所有属性
        AttrGroupEntity attrGroupEntity = attrGroupDao.selectById(attrgroupId);
        Long catelogId = attrGroupEntity.getCatelogId();
        //2.当前分组只能关联别的分组没有引用的属性
        //2.1当前分类下的其他分组
        List<AttrGroupEntity> group = attrGroupDao.selectList(new QueryWrapper<AttrGroupEntity>().eq("catelog_id", catelogId));
        //2.2这些分组关联的属性
        //先从group中获取到所有attrgroupId构成的集合
        List<Long> attrgroupIdCollect = group.stream().map((item) -> {
            return item.getAttrGroupId();
        }).collect(Collectors.toList());
        List<AttrAttrgroupRelationEntity> middle = attrAttrgroupRelationDao.selectList(new QueryWrapper<AttrAttrgroupRelationEntity>().in("attr_group_id", attrgroupIdCollect));
        //2.3从当前分类的所有属性中移除这些属性
        List<Long> attrIdsCollect = middle.stream().map((item) -> {
            return item.getAttrId();
        }).collect(Collectors.toList());
        QueryWrapper<AttrEntity> wrapper = new QueryWrapper<AttrEntity>().eq("catelog_id",catelogId).eq("attr_type",ProductConstant.AttrEnum.ATTR_TYPE_BASE.getCode());

        if(attrIdsCollect != null && attrIdsCollect.size() > 0){
            wrapper.notIn("attr_id", attrIdsCollect);
        }

        String key = (String)params.get("key");
        if(!StringUtils.isEmpty(key)){
            wrapper.and((w) -> {
                w.eq("attr_id",key).or().like("attr_name",key);
            });
        }
        IPage<AttrEntity> page = this.page(
                new Query<AttrEntity>().getPage(params),
                wrapper
        );

        return new PageUtils(page);
    }

    private List<Long> getCatelogPath(Long catelogId, List<Long> list){
        list.add(catelogId);
        CategoryEntity categoryEntity = categoryDao.selectById(catelogId);
        if(categoryEntity.getParentCid() != 0){
            getCatelogPath(categoryEntity.getParentCid(),list);
        }
        return list;
    }


}